Bibliotecas
library(tidyverse)
Warning: package ‘tidyverse’ was built under R version 4.3.2Warning: package ‘ggplot2’ was built under R version 4.3.3Warning: package ‘tidyr’ was built under R version 4.3.3Warning: package ‘readr’ was built under R version 4.3.2Warning: package ‘purrr’ was built under R version 4.3.2Warning: package ‘dplyr’ was built under R version 4.3.2Warning: package ‘stringr’ was built under R version 4.3.2Warning: package ‘forcats’ was built under R version 4.3.1Warning: package ‘lubridate’ was built under R version 4.3.2── Attaching core tidyverse packages ───────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.4
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.5.0 ✔ tibble 3.2.1
✔ lubridate 1.9.3 ✔ tidyr 1.3.1
✔ purrr 1.0.2 ── Conflicts ─────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(here)
here() starts at C:/Users/Wasim/OneDrive/Área de Trabalho/Github/upvacina
library(readxl)
Warning: package ‘readxl’ was built under R version 4.3.2
library(janitor)
Warning: package ‘janitor’ was built under R version 4.3.2
Attaching package: ‘janitor’
The following objects are masked from ‘package:stats’:
chisq.test, fisher.test
library(stringi)
Warning: package ‘stringi’ was built under R version 4.3.2
Unindo tabelas
Dados de estados
lista_UF_cobertura = list.files()
# Lista todos os arquivos CSV no diretório
arquivos_xlsx <- list.files(here(), pattern = "\\.xlsx$", full.names = F)
#Criar funcao
read_xl_sipni <- function(arquivo) {
dados <- read_excel(arquivo, skip = 4, col_names = FALSE) %>%
setNames(.[1, ]) %>%
slice(-1:-4) %>%
mutate(across(-1, as.numeric)) %>%
pivot_longer(cols = -c(1),
names_to = "imuno",
values_to = "cobertura") %>%
mutate(arquivo = basename(arquivo)) %>%
janitor::clean_names() %>%
mutate(cobertura = round(cobertura, 2),
ano = as.numeric(gsub(".*_(\\d{4})\\.xlsx", "\\1", arquivo)),
uf = gsub("\\d", "", .[[1]])) %>%
select(-unidade_da_federacao) %>%
filter(!is.na(uf),
!grepl("Gerado", uf)) %>%
select(uf, ano, imuno, cobertura) %>%
group_by(uf, ano, imuno)
return(dados)
}
# Leia, converta em tabela longa e combine os arquivos CSV em um único DataFrame
sipni_cobertura_uf_1994_2023 <- lapply(arquivos_xlsx, read_xl_sipni) %>%
bind_rows()
saveRDS(sipni_cobertura_uf_1994_2023, file = "sipni_cobertura_uf_1994_2023.rds")
Dados de municípios
#Listar tabelas
lista_MU_cobertura = list.files()
arquivos_xlsx <- list.files(here(), pattern = "\\.xlsx$", full.names = F)
#Criar função
read_xl_sipni_municipio <- function(arquivo) {
dados <- read_excel(arquivo, skip = 4, col_names = FALSE) %>%
setNames(.[1, ]) %>%
slice(-1:-4) %>%
mutate(across(-1, as.numeric)) %>%
pivot_longer(cols = -c(1),
names_to = "imuno",
values_to = "cobertura") %>%
mutate(arquivo = basename(arquivo)) %>%
janitor::clean_names() %>%
mutate(cobertura = round(cobertura, 2),
ano = as.numeric(gsub(".*_(\\d{4})\\.xlsx", "\\1", arquivo))) %>%
filter(!is.na(municipio),
!grepl("Gerado", municipio)) %>%
select(municipio, ano, imuno, cobertura) %>%
group_by(municipio, ano, imuno)
return(dados)
}
#Unir dados
sipni_cobertura_municipios_1994_2023 <- lapply(arquivos_xlsx, read_xl_sipni_municipio) %>%
bind_rows()
#Salvar
saveRDS(sipni_cobertura_municipios_1994_2023,
file = "sipni_cobertura_municipios_1994_2023.rds")
Processamento de dados
#Estados
sipni_cobertura_uf_1994_2023_2 = sipni_cobertura_uf_1994_2023 %>%
mutate(mun_uf = "UF",
nome = uf,
nome = toupper(nome),
nome = stri_trans_general(nome, "Latin-ASCII")) %>%
select(nome, uf, ano, imuno, cobertura, mun_uf)
saveRDS(sipni_cobertura_uf_1994_2023_2, file = "sipni_cobertura_uf_1994_2023_2.rds")
#Municípios
sipni_cobertura_municipios_1994_2023_2 = sipni_cobertura_municipios_1994_2023 %>%
mutate(codigo = as.character(str_extract(municipio, "\\d+")),# Extrair números
nome = str_remove(municipio, "\\d+ "),# Extrair texto
mun_uf = "Município" ) %>%
select(!"...1":municipio)
glimpse(sipni_cobertura_municipios_1994_2023_2)
# #Unir
# sipni_all = bind_rows(sipni_cobertura_uf_1994_2023_2, sipni_cobertura_municipios_1994_2023_2)
# write.csv(sipni_all, file = "sipni_uf_mun_1994_2023.csv")
#Anotar municipios e estados
#Anotações de cidades. Fonte: IBGE. https://www.ibge.gov.br/explica/codigos-dos-municipios.php
dtb_municipios_cod = RELATORIO_DTB_BRASIL_MUNICIPIO %>%
clean_names() %>%
select(codigo_uf = uf, uf = nome_uf, codigo = codigo_municipio_completo, nome_municipio) %>%
mutate(nome_municipio_original = nome_municipio,
nome = toupper(nome_municipio_original),
nome = stri_trans_general(nome, "Latin-ASCII")) %>%
select(-nome_municipio)
municipios = sipni_cobertura_municipios_1994_2023_2 %>%
mutate(nome = gsub("\\\\", "", nome)) %>%
left_join(dtb_municipios_cod, by = "nome") %>%
select(nome, nome_municipio_original, uf, codigo_municipio = codigo.y, ano, imuno, cobertura, codigo_uf, mun_uf)
#Salvar
saveRDS(municipios, file = "sipni_cobertura_municipios_1994_2023_2.rds")
#Análise de dados Os dados das populações foram obtidos dos anos 2000
a 2022, pois os anos 2007 e 2023 não estavam disponíveis. Definir
variáveis - https://www.ibge.gov.br/estatisticas/downloads-estatisticas.html
- Censos - Perfil Estados - Perfil Municipios - Economicos - Indicadores
sociais - Educacação e qualificação profissional - Economia de saúde -
Acesso à internet - Educação - Saúde
install.packages("basedosdados")
library("basedosdados")
# Para carregar o dado direto no R
query <- bdplyr("br_ibge_censo_demografico.microdados_domicilio_1970")
df <- bd_collect(query)
install.packages("bdplyr")
query <- bdplyr("br_ms_atencao_basica.municipio")
df <- bd_collect(query)
# População ----
# Obter população de municipios.
anos = 2000:2023
resultados = list()
for (ano in anos) {
tryCatch({
# Chamar a função populacao_municipios para o ano atual e armazenar o resultado na lista
df_ano <- populacao_municipios(ano)
df_ano <- df_ano %>%
mutate_all(as.character) # Convertendo todas as colunas para character
resultados[[as.character(ano)]] <- df_ano
}, error = function(e) {
# Tratar o erro (por exemplo, imprimir uma mensagem)
print(paste("Erro para o ano", ano, ":", conditionMessage(e)))
})
}
# Combinar todos os dataframes em um único dataframe
populacao_municipios_2000_2022 <- bind_rows(resultados, .id = "ano") %>%
select(uf_abrev = uf,
nome_municipio_original = nome_munic,
ano, codigo_uf,
populacao,
codigo_municipio = cod_municipio) %>%
mutate(ano = as.numeric(ano),
populacao = as.numeric(populacao))
print(populacao_municipios_2000_2022)
# GDP ----
anos = 1999:2020
pib_municipios(ano = 2003)
resultados = list()
for (ano in anos) {
tryCatch({
df_ano <- pib_municipios(ano = ano, dir=".")
resultados[[ano]] <- df_ano
}, error = function(e) {
print(paste("Erro para o ano", ano, ":", conditionMessage(e)))
})
}
# Combinar todos os dataframes em um único dataframe
populacao_municipios_2000_2022 <- bind_rows(resultados, .id = "ano") %>%
select(uf_abrev = uf,
nome_municipio_original = nome_munic,
ano, codigo_uf,
populacao,
codigo_municipio = cod_municipio) %>%
mutate(ano = as.numeric(ano),
populacao = as.numeric(populacao))
print(populacao_municipios_2000_2022)
#Unir dados
municipios_2 = municipios %>%
left_join(populacao_municipios_2000_2022 %>%
select(codigo_municipio, ano, populacao),
by = c("codigo_municipio", "ano"))
#IEPS dados
LS0tDQp0aXRsZTogIlVQVmFjaW5hIC0gRGFkb3MgU0lQTkkiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIEJpYmxpb3RlY2FzDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShoZXJlKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KGphbml0b3IpDQpsaWJyYXJ5KHN0cmluZ2kpDQpgYGANCg0KIyBVbmluZG8gdGFiZWxhcw0KDQpEYWRvcyBkZSBlc3RhZG9zDQpgYGB7cn0NCmxpc3RhX1VGX2NvYmVydHVyYSA9IGxpc3QuZmlsZXMoKSANCg0KIyBMaXN0YSB0b2RvcyBvcyBhcnF1aXZvcyBDU1Ygbm8gZGlyZXTDs3Jpbw0KYXJxdWl2b3NfeGxzeCA8LSBsaXN0LmZpbGVzKGhlcmUoKSwgcGF0dGVybiA9ICJcXC54bHN4JCIsIGZ1bGwubmFtZXMgPSBGKQ0KDQojQ3JpYXIgZnVuY2FvDQpyZWFkX3hsX3NpcG5pIDwtIGZ1bmN0aW9uKGFycXVpdm8pIHsNCiAgZGFkb3MgPC0gcmVhZF9leGNlbChhcnF1aXZvLCBza2lwID0gNCwgY29sX25hbWVzID0gRkFMU0UpICU+JQ0KICAgIHNldE5hbWVzKC5bMSwgXSkgJT4lDQogICAgc2xpY2UoLTE6LTQpICU+JQ0KICAgIG11dGF0ZShhY3Jvc3MoLTEsIGFzLm51bWVyaWMpKSAlPiUgIA0KICAgIHBpdm90X2xvbmdlcihjb2xzID0gLWMoMSksIA0KICAgICAgICAgICAgICAgICBuYW1lc190byA9ICJpbXVubyIsIA0KICAgICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiY29iZXJ0dXJhIikgJT4lIA0KICAgIG11dGF0ZShhcnF1aXZvID0gYmFzZW5hbWUoYXJxdWl2bykpICU+JSANCiAgICBqYW5pdG9yOjpjbGVhbl9uYW1lcygpICU+JSANCiAgICBtdXRhdGUoY29iZXJ0dXJhID0gcm91bmQoY29iZXJ0dXJhLCAyKSwNCiAgICAgICAgICAgYW5vID0gYXMubnVtZXJpYyhnc3ViKCIuKl8oXFxkezR9KVxcLnhsc3giLCAiXFwxIiwgYXJxdWl2bykpLA0KICAgICAgICAgICB1ZiA9IGdzdWIoIlxcZCIsICIiLCAuW1sxXV0pKSAgJT4lIA0KICAgIHNlbGVjdCgtdW5pZGFkZV9kYV9mZWRlcmFjYW8pICU+JSANCiAgICBmaWx0ZXIoIWlzLm5hKHVmKSwNCiAgICAgICAgICAgIWdyZXBsKCJHZXJhZG8iLCB1ZikpICU+JSANCiAgICBzZWxlY3QodWYsIGFubywgaW11bm8sIGNvYmVydHVyYSkgJT4lIA0KICAgIGdyb3VwX2J5KHVmLCBhbm8sIGltdW5vKQ0KICANCiAgcmV0dXJuKGRhZG9zKQ0KfQ0KDQoNCiMgTGVpYSwgY29udmVydGEgZW0gdGFiZWxhIGxvbmdhIGUgY29tYmluZSBvcyBhcnF1aXZvcyBDU1YgZW0gdW0gw7puaWNvIERhdGFGcmFtZQ0Kc2lwbmlfY29iZXJ0dXJhX3VmXzE5OTRfMjAyMyA8LSBsYXBwbHkoYXJxdWl2b3NfeGxzeCwgcmVhZF94bF9zaXBuaSkgJT4lDQogIGJpbmRfcm93cygpDQoNCnNhdmVSRFMoc2lwbmlfY29iZXJ0dXJhX3VmXzE5OTRfMjAyMywgZmlsZSA9ICJzaXBuaV9jb2JlcnR1cmFfdWZfMTk5NF8yMDIzLnJkcyIpDQpgYGANCg0KDQpEYWRvcyBkZSBtdW5pY8OtcGlvcw0KYGBge3J9DQojTGlzdGFyIHRhYmVsYXMNCmxpc3RhX01VX2NvYmVydHVyYSA9IGxpc3QuZmlsZXMoKSANCmFycXVpdm9zX3hsc3ggPC0gbGlzdC5maWxlcyhoZXJlKCksIHBhdHRlcm4gPSAiXFwueGxzeCQiLCBmdWxsLm5hbWVzID0gRikNCg0KI0NyaWFyIGZ1bsOnw6NvDQpyZWFkX3hsX3NpcG5pX211bmljaXBpbyA8LSBmdW5jdGlvbihhcnF1aXZvKSB7DQogIGRhZG9zIDwtIHJlYWRfZXhjZWwoYXJxdWl2bywgc2tpcCA9IDQsIGNvbF9uYW1lcyA9IEZBTFNFKSAlPiUNCiAgICBzZXROYW1lcyguWzEsIF0pICU+JQ0KICAgIHNsaWNlKC0xOi00KSAlPiUNCiAgICBtdXRhdGUoYWNyb3NzKC0xLCBhcy5udW1lcmljKSkgJT4lICANCiAgICBwaXZvdF9sb25nZXIoY29scyA9IC1jKDEpLCANCiAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiaW11bm8iLCANCiAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImNvYmVydHVyYSIpICU+JSANCiAgICBtdXRhdGUoYXJxdWl2byA9IGJhc2VuYW1lKGFycXVpdm8pKSAlPiUgDQogICAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgDQogICAgbXV0YXRlKGNvYmVydHVyYSA9IHJvdW5kKGNvYmVydHVyYSwgMiksDQogICAgICAgICAgIGFubyA9IGFzLm51bWVyaWMoZ3N1YigiLipfKFxcZHs0fSlcXC54bHN4IiwgIlxcMSIsIGFycXVpdm8pKSkgJT4lIA0KICAgIGZpbHRlcighaXMubmEobXVuaWNpcGlvKSwNCiAgICAgICAgICAgIWdyZXBsKCJHZXJhZG8iLCBtdW5pY2lwaW8pKSAlPiUgDQogICAgc2VsZWN0KG11bmljaXBpbywgYW5vLCBpbXVubywgY29iZXJ0dXJhKSAlPiUgDQogICAgZ3JvdXBfYnkobXVuaWNpcGlvLCBhbm8sIGltdW5vKQ0KICANCiAgcmV0dXJuKGRhZG9zKQ0KfQ0KDQojVW5pciBkYWRvcw0Kc2lwbmlfY29iZXJ0dXJhX211bmljaXBpb3NfMTk5NF8yMDIzIDwtIGxhcHBseShhcnF1aXZvc194bHN4LCByZWFkX3hsX3NpcG5pX211bmljaXBpbykgJT4lDQogIGJpbmRfcm93cygpDQoNCiNTYWx2YXINCnNhdmVSRFMoc2lwbmlfY29iZXJ0dXJhX211bmljaXBpb3NfMTk5NF8yMDIzLCANCiAgICAgICAgICBmaWxlID0gInNpcG5pX2NvYmVydHVyYV9tdW5pY2lwaW9zXzE5OTRfMjAyMy5yZHMiKQ0KYGBgDQoNCiMgUHJvY2Vzc2FtZW50byBkZSBkYWRvcw0KYGBge3J9DQojRXN0YWRvcw0Kc2lwbmlfY29iZXJ0dXJhX3VmXzE5OTRfMjAyM18yID0gc2lwbmlfY29iZXJ0dXJhX3VmXzE5OTRfMjAyMyAlPiUgDQogIG11dGF0ZShtdW5fdWYgPSAiVUYiLCANCiAgICAgICAgIG5vbWUgPSB1ZiwNCiAgICAgICAgIG5vbWUgPSAgdG91cHBlcihub21lKSwNCiAgICAgICAgIG5vbWUgPSBzdHJpX3RyYW5zX2dlbmVyYWwobm9tZSwgIkxhdGluLUFTQ0lJIikpICU+JSANCiAgc2VsZWN0KG5vbWUsIHVmLCBhbm8sIGltdW5vLCBjb2JlcnR1cmEsIG11bl91ZikNCg0Kc2F2ZVJEUyhzaXBuaV9jb2JlcnR1cmFfdWZfMTk5NF8yMDIzXzIsIGZpbGUgPSAic2lwbmlfY29iZXJ0dXJhX3VmXzE5OTRfMjAyM18yLnJkcyIpDQoNCiNNdW5pY8OtcGlvcw0Kc2lwbmlfY29iZXJ0dXJhX211bmljaXBpb3NfMTk5NF8yMDIzXzIgPSBzaXBuaV9jb2JlcnR1cmFfbXVuaWNpcGlvc18xOTk0XzIwMjMgJT4lIA0KIG11dGF0ZShjb2RpZ28gPSBhcy5jaGFyYWN0ZXIoc3RyX2V4dHJhY3QobXVuaWNpcGlvLCAiXFxkKyIpKSwjIEV4dHJhaXIgbsO6bWVyb3MNCiAgICAgICAgbm9tZSA9IHN0cl9yZW1vdmUobXVuaWNpcGlvLCAiXFxkKyAiKSwjIEV4dHJhaXIgdGV4dG8NCiAgICAgICAgbXVuX3VmID0gIk11bmljw61waW8iICkgJT4lIA0KICBzZWxlY3QoISIuLi4xIjptdW5pY2lwaW8pDQoNCmdsaW1wc2Uoc2lwbmlfY29iZXJ0dXJhX211bmljaXBpb3NfMTk5NF8yMDIzXzIpDQoNCiMgI1VuaXINCiMgc2lwbmlfYWxsID0gYmluZF9yb3dzKHNpcG5pX2NvYmVydHVyYV91Zl8xOTk0XzIwMjNfMiwgc2lwbmlfY29iZXJ0dXJhX211bmljaXBpb3NfMTk5NF8yMDIzXzIpDQojIHdyaXRlLmNzdihzaXBuaV9hbGwsIGZpbGUgPSAic2lwbmlfdWZfbXVuXzE5OTRfMjAyMy5jc3YiKQ0KDQpgYGANCg0KDQojQW5vdGFyIG11bmljaXBpb3MgZSBlc3RhZG9zIA0KDQpgYGB7cn0NCiNBbm90YcOnw7VlcyBkZSBjaWRhZGVzLiBGb250ZTogSUJHRS4gaHR0cHM6Ly93d3cuaWJnZS5nb3YuYnIvZXhwbGljYS9jb2RpZ29zLWRvcy1tdW5pY2lwaW9zLnBocA0KZHRiX211bmljaXBpb3NfY29kID0gUkVMQVRPUklPX0RUQl9CUkFTSUxfTVVOSUNJUElPICU+JSANCiAgY2xlYW5fbmFtZXMoKSAlPiUgDQogIHNlbGVjdChjb2RpZ29fdWYgPSB1ZiwgdWYgPSBub21lX3VmLCBjb2RpZ28gPSBjb2RpZ29fbXVuaWNpcGlvX2NvbXBsZXRvLCBub21lX211bmljaXBpbykgJT4lIA0KICBtdXRhdGUobm9tZV9tdW5pY2lwaW9fb3JpZ2luYWwgPSBub21lX211bmljaXBpbywNCiAgICAgICAgIG5vbWUgPSAgdG91cHBlcihub21lX211bmljaXBpb19vcmlnaW5hbCksDQogICAgICAgICBub21lID0gc3RyaV90cmFuc19nZW5lcmFsKG5vbWUsICJMYXRpbi1BU0NJSSIpKSAlPiUgDQogIHNlbGVjdCgtbm9tZV9tdW5pY2lwaW8pDQoNCm11bmljaXBpb3MgPSBzaXBuaV9jb2JlcnR1cmFfbXVuaWNpcGlvc18xOTk0XzIwMjNfMiAlPiUgDQogIG11dGF0ZShub21lID0gZ3N1YigiXFxcXCIsICIiLCBub21lKSkgJT4lIA0KICBsZWZ0X2pvaW4oZHRiX211bmljaXBpb3NfY29kLCBieSA9ICJub21lIikgJT4lIA0KICBzZWxlY3Qobm9tZSwgbm9tZV9tdW5pY2lwaW9fb3JpZ2luYWwsIHVmLCBjb2RpZ29fbXVuaWNpcGlvID0gY29kaWdvLnksIGFubywgaW11bm8sIGNvYmVydHVyYSwgY29kaWdvX3VmLCBtdW5fdWYpDQoNCiNTYWx2YXINCnNhdmVSRFMobXVuaWNpcGlvcywgZmlsZSA9ICJzaXBuaV9jb2JlcnR1cmFfbXVuaWNpcGlvc18xOTk0XzIwMjNfMi5yZHMiKQ0KICANCmBgYA0KDQoNCiNBbsOhbGlzZSBkZSBkYWRvcw0KT3MgZGFkb3MgZGFzIHBvcHVsYcOnw7VlcyBmb3JhbSBvYnRpZG9zIGRvcyBhbm9zIDIwMDAgYSAyMDIyLCBwb2lzIG9zIGFub3MgMjAwNyBlIDIwMjMgbsOjbyBlc3RhdmFtIGRpc3BvbsOtdmVpcy4NCkRlZmluaXIgdmFyacOhdmVpcw0KLSBodHRwczovL3d3dy5pYmdlLmdvdi5ici9lc3RhdGlzdGljYXMvZG93bmxvYWRzLWVzdGF0aXN0aWNhcy5odG1sIA0KLSBDZW5zb3MNCi0gUGVyZmlsIEVzdGFkb3MNCi0gUGVyZmlsIE11bmljaXBpb3MNCi0gRWNvbm9taWNvcw0KLSBJbmRpY2Fkb3JlcyBzb2NpYWlzDQotIEVkdWNhY2HDp8OjbyBlIHF1YWxpZmljYcOnw6NvIHByb2Zpc3Npb25hbA0KLSBFY29ub21pYSBkZSBzYcO6ZGUNCi0gQWNlc3NvIMOgIGludGVybmV0DQotIEVkdWNhw6fDo28NCi0gU2HDumRlDQoNCmBgYHtyfQ0KaW5zdGFsbC5wYWNrYWdlcygiYmFzZWRvc2RhZG9zIikNCmxpYnJhcnkoImJhc2Vkb3NkYWRvcyIpDQoNCiMgUGFyYSBjYXJyZWdhciBvIGRhZG8gZGlyZXRvIG5vIFINCnF1ZXJ5IDwtIGJkcGx5cigiYnJfaWJnZV9jZW5zb19kZW1vZ3JhZmljby5taWNyb2RhZG9zX2RvbWljaWxpb18xOTcwIikNCmRmIDwtIGJkX2NvbGxlY3QocXVlcnkpDQoNCg0KaW5zdGFsbC5wYWNrYWdlcygiYmRwbHlyIikNCnF1ZXJ5IDwtIGJkcGx5cigiYnJfbXNfYXRlbmNhb19iYXNpY2EubXVuaWNpcGlvIikNCmRmIDwtIGJkX2NvbGxlY3QocXVlcnkpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KIyBQb3B1bGHDp8OjbyAtLS0tIA0KDQojIE9idGVyIHBvcHVsYcOnw6NvIGRlIG11bmljaXBpb3MuDQphbm9zID0gMjAwMDoyMDIzDQpyZXN1bHRhZG9zID0gbGlzdCgpDQpmb3IgKGFubyBpbiBhbm9zKSB7DQogIHRyeUNhdGNoKHsNCiAgICAjIENoYW1hciBhIGZ1bsOnw6NvIHBvcHVsYWNhb19tdW5pY2lwaW9zIHBhcmEgbyBhbm8gYXR1YWwgZSBhcm1hemVuYXIgbyByZXN1bHRhZG8gbmEgbGlzdGENCiAgICBkZl9hbm8gPC0gcG9wdWxhY2FvX211bmljaXBpb3MoYW5vKQ0KICAgIGRmX2FubyA8LSBkZl9hbm8gJT4lDQogICAgICBtdXRhdGVfYWxsKGFzLmNoYXJhY3RlcikgICMgQ29udmVydGVuZG8gdG9kYXMgYXMgY29sdW5hcyBwYXJhIGNoYXJhY3Rlcg0KICAgIHJlc3VsdGFkb3NbW2FzLmNoYXJhY3Rlcihhbm8pXV0gPC0gZGZfYW5vDQogIH0sIGVycm9yID0gZnVuY3Rpb24oZSkgew0KICAgICMgVHJhdGFyIG8gZXJybyAocG9yIGV4ZW1wbG8sIGltcHJpbWlyIHVtYSBtZW5zYWdlbSkNCiAgICBwcmludChwYXN0ZSgiRXJybyBwYXJhIG8gYW5vIiwgYW5vLCAiOiIsIGNvbmRpdGlvbk1lc3NhZ2UoZSkpKQ0KICB9KQ0KfQ0KDQojIENvbWJpbmFyIHRvZG9zIG9zIGRhdGFmcmFtZXMgZW0gdW0gw7puaWNvIGRhdGFmcmFtZQ0KcG9wdWxhY2FvX211bmljaXBpb3NfMjAwMF8yMDIyIDwtIGJpbmRfcm93cyhyZXN1bHRhZG9zLCAuaWQgPSAiYW5vIikgJT4lIA0KICBzZWxlY3QodWZfYWJyZXYgPSB1ZiwgDQogICAgICAgICBub21lX211bmljaXBpb19vcmlnaW5hbCA9IG5vbWVfbXVuaWMsDQogICAgICAgICBhbm8sIGNvZGlnb191ZiwgDQogICAgICAgICBwb3B1bGFjYW8sIA0KICAgICAgICAgY29kaWdvX211bmljaXBpbyA9IGNvZF9tdW5pY2lwaW8pICU+JSANCiAgbXV0YXRlKGFubyA9IGFzLm51bWVyaWMoYW5vKSwNCiAgICAgICAgIHBvcHVsYWNhbyA9IGFzLm51bWVyaWMocG9wdWxhY2FvKSkNCiAgDQpwcmludChwb3B1bGFjYW9fbXVuaWNpcGlvc18yMDAwXzIwMjIpDQoNCg0KIyBHRFAgLS0tLQ0KDQphbm9zID0gMTk5OToyMDIwDQpwaWJfbXVuaWNpcGlvcyhhbm8gPSAyMDAzKQ0KDQpyZXN1bHRhZG9zID0gbGlzdCgpDQpmb3IgKGFubyBpbiBhbm9zKSB7DQogIHRyeUNhdGNoKHsNCiAgICBkZl9hbm8gPC0gcGliX211bmljaXBpb3MoYW5vID0gYW5vLCBkaXI9Ii4iKQ0KICAgIHJlc3VsdGFkb3NbW2Fub11dIDwtIGRmX2Fubw0KICB9LCBlcnJvciA9IGZ1bmN0aW9uKGUpIHsNCiAgICBwcmludChwYXN0ZSgiRXJybyBwYXJhIG8gYW5vIiwgYW5vLCAiOiIsIGNvbmRpdGlvbk1lc3NhZ2UoZSkpKQ0KICB9KQ0KfQ0KDQojIENvbWJpbmFyIHRvZG9zIG9zIGRhdGFmcmFtZXMgZW0gdW0gw7puaWNvIGRhdGFmcmFtZQ0KcG9wdWxhY2FvX211bmljaXBpb3NfMjAwMF8yMDIyIDwtIGJpbmRfcm93cyhyZXN1bHRhZG9zLCAuaWQgPSAiYW5vIikgJT4lIA0KICBzZWxlY3QodWZfYWJyZXYgPSB1ZiwgDQogICAgICAgICBub21lX211bmljaXBpb19vcmlnaW5hbCA9IG5vbWVfbXVuaWMsDQogICAgICAgICBhbm8sIGNvZGlnb191ZiwgDQogICAgICAgICBwb3B1bGFjYW8sIA0KICAgICAgICAgY29kaWdvX211bmljaXBpbyA9IGNvZF9tdW5pY2lwaW8pICU+JSANCiAgbXV0YXRlKGFubyA9IGFzLm51bWVyaWMoYW5vKSwNCiAgICAgICAgIHBvcHVsYWNhbyA9IGFzLm51bWVyaWMocG9wdWxhY2FvKSkNCiAgDQpwcmludChwb3B1bGFjYW9fbXVuaWNpcGlvc18yMDAwXzIwMjIpDQpgYGANCg0KDQpgYGB7cn0NCiNVbmlyIGRhZG9zDQoNCm11bmljaXBpb3NfMiA9IG11bmljaXBpb3MgJT4lIA0KIGxlZnRfam9pbihwb3B1bGFjYW9fbXVuaWNpcGlvc18yMDAwXzIwMjIgJT4lIA0KICAgICAgICAgICAgIHNlbGVjdChjb2RpZ29fbXVuaWNpcGlvLCBhbm8sIHBvcHVsYWNhbyksDQogICAgICAgICAgICBieSA9IGMoImNvZGlnb19tdW5pY2lwaW8iLCAiYW5vIikpDQoNCg0KDQpgYGANCg0KDQojSUVQUyBkYWRvcw0KDQoNCmBgYHtyfQ0KDQojVW5pciBkYWRvcw0KSUVQU19CcmFzaWxfMjAxMF8yMDIyX1RvZG9zIDwtIHJlYWRfZXhjZWwoImRhZG9zX2JydXRvcy9JRVBTL0lFUFNfQnJhc2lsXzIwMTBfMjAyMl9Ub2Rvcy54bHN4IikgJT4lIA0KICBtdXRhdGUobml2ZWwgPSAiQnJhc2lsIikNCklFUFNfRXN0YWRvc18yMDEwXzIwMjJfVG9kb3MgPC0gcmVhZF9leGNlbCgiZGFkb3NfYnJ1dG9zL0lFUFMvSUVQU19Fc3RhZG9zXzIwMTBfMjAyMl9Ub2Rvcy54bHN4IikgJT4lIA0KICBtdXRhdGUobml2ZWwgPSAiRXN0YWRvIikNCklFUFNfTWFjcm9SZWdpYW9fMjAxMF8yMDIyX1RvZG9zIDwtIHJlYWRfZXhjZWwoImRhZG9zX2JydXRvcy9JRVBTL0lFUFNfTWFjcm9SZWdpYW9fMjAxMF8yMDIyX1RvZG9zLnhsc3giKSAlPiUgDQogIG11dGF0ZShuaXZlbCA9ICJNYWNybyBSZWdpw6NvIikNCklFUFNfTXVuaWNpcGlvc18yMDEwXzIwMjJfVG9kb3MgPC0gcmVhZF9leGNlbCgiZGFkb3NfYnJ1dG9zL0lFUFMvSUVQU19NdW5pY2lwaW9zXzIwMTBfMjAyMl9Ub2Rvcy54bHN4IikgJT4lIA0KICBtdXRhdGUobml2ZWwgPSAiTXVuaWPDrXBpbyIpDQpJRVBTX1JlZ2lhb18yMDEwXzIwMjJfVG9kb3MgPC0gcmVhZF9leGNlbCgiZGFkb3NfYnJ1dG9zL0lFUFMvSUVQU19SZWdpYW9fMjAxMF8yMDIyX1RvZG9zLnhsc3giKSAlPiUgDQogIG11dGF0ZShuaXZlbCA9ICJSZWdpw6NvIikNCg0KDQpJRVBTX0NvbXBsZXRvXzIwMTBfMjAyMl9Ub2RvcyA9IGJpbmRfcm93cyhJRVBTX0JyYXNpbF8yMDEwXzIwMjJfVG9kb3MsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJRVBTX0VzdGFkb3NfMjAxMF8yMDIyX1RvZG9zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSUVQU19NYWNyb1JlZ2lhb18yMDEwXzIwMjJfVG9kb3MsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJRVBTX1JlZ2lhb18yMDEwXzIwMjJfVG9kb3MpDQoNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0K